Add support for name_to_handle_at(2), open_by_handle_at(2) on Linux#1517
Add support for name_to_handle_at(2), open_by_handle_at(2) on Linux#1517bertschingert wants to merge 4 commits intobytecodealliance:mainfrom
Conversation
9638fd6 to
35587db
Compare
This way, once the user gets it, the filehandle slice is only as large as it needs to be. Then if the user copies it, excess unused bytes are not copied.
|
|
||
| /// This maximum is more of a "guideline"; the man page for name_to_handle_at(2) indicates it could | ||
| /// increase in the future. | ||
| const MAX_HANDLE_SIZE: usize = 128; |
There was a problem hiding this comment.
Does this correspond to MAX_HANDLE_SZ in libc? If so, could you add a comment about this?
|
Currently, tests requiring non-default Linux capabilities are just I myself don't know anything about Concerning 2, I agree an API to avoid the Concerning 3, rustix tries to guess whether use cases using these functions would have a need to decide which variant to use dynamically. If so, then it makes more sense to do an |
cyphar
left a comment
There was a problem hiding this comment.
Seems quite reasonable, my only strong comment is about MountId.
| /// An identifier for a mount that is returned by [`name_to_handle_at`]. | ||
| /// | ||
| /// [`name_to_handle_at`]: crate::fs::name_to_handle_at | ||
| #[derive(Debug)] | ||
| pub enum MountId { | ||
| /// By default a MountId is a C int. | ||
| Regular(ffi::c_int), | ||
| /// When `AT_HANDLE_MNT_ID_UNIQUE` is passed in `HandleFlags`, MountId is a u64. | ||
| Unique(u64), | ||
| } |
There was a problem hiding this comment.
I would honestly just suggest using a u64 in the API for both and not bothering with this split, it's just more annoying for callers and there's no real benefit to getting less bits for classic mount IDs (IMHO).
This is also what Statx::stx_mnt_id does (statx even has the same flag-based behaviour -- in fact, I picked the AT_HANDLE_MNT_ID_UNIQUE to match the name of the STATX_ flag). (Though Statx does that because it matches the kernel struct definition.)
| } | ||
|
|
||
| /// Set the `handle_bytes` field (first 4 bytes of the struct) to the given length. | ||
| fn set_handle_bytes(&mut self, size: usize) { |
There was a problem hiding this comment.
nit: This is the name of the field but this just looks confusing in Rust code -- you're getting and setting the length of the byte slice, so set_handle_len seems more appropriate in Rust.
| /// Get the raw bytes of a file handle. | ||
| pub fn into_raw(self) -> Box<[u8]> { | ||
| self.raw | ||
| } |
There was a problem hiding this comment.
It would be nice to have an as_raw too imho.
This adds support for
{name_to,open_by}_handle_at(2)on Linux.I have a Rust application that wants to use these syscalls and it would be really nice to use a standard library rather than roll my own wrappers.
I would consider this an RFC at this point because I do have a few open questions about the API:
handle_bytesandhandle_typefields, even though they are exposed in the C struct definition. (Thehandle_bytesfield does need to be accessed to size the handle correctly, but that is handled by this library, so user apps need not worry about that.) So this API makesstruct FileHandleentirely opaque. If I'm wrong and there is a valid reason for a user app to access those fields, I think getter/setters could be added in the future without breaking the API...BorrowedFileHandletype that contains&[u8]instead ofBox<[u8]>-- I don't immediately have a use case for it, so I didn't implement it, but putting it out there in case the idea does seem usefulname_to_handle_at(2)is interesting in that its signature is different depending on the flagAT_HANDLE_MNT_ID_UNIQUE-- themount_idparameter is either anint *, oru64 *. I thought of two ways to handle this in rust: create a separatename_to_handle_at_unique()function for theu64variant, or create an Enum so that one function can return both kinds of mount_id. I went with the latter, but I could see an argument for the former being better. Thoughts?I want to be able to store a filehandle and/or send it over the network, and then use it again when I get it back, so that is the reason for adding public
from_raw()andinto_raw()methods ontostruct FileHandle.Another question is how to test this -- since open_by_handle_at(2) requires CAP_DAC_READ_SEARCH privilege, programs that use it typically run as root. Is there a precedent for how to write unit/integration tests that require root in Rustix? (I have an external test program I ran with sudo to test this, I can share it if that would be helpful.)